#ifndef _DATA_ACCESSOR_H_
#define _DATA_ACCESSOR_H_

#include "collaboration.h"
#include "dbAccessor.h"

/**
* Clase que permite acceder al almacen de metainformacion del sistema.
* Permite abstraer del modelo de almacenamiento de datos usado y acceder
* a este sistema de almacenamiento de forma remota. Implementa el esqueleto
* generado a partir del fichero idl de definicion de interfaces CORBA.
*
* @author Carlos Rodriguez Dominguez
*/
class MIDataAccessor_impl: public POA_collaboration::MIDataAccessor {
private:
	collaboration::ListOfApplications* m_applications; /**< Conjunto de aplicaciones del sistema */
	DBAccessor* m_reader; /**< Lector de datos. En este caso se usa un lector de una BD */
	
	/**
	* Obtiene la posicion en el vector de usuarios de una aplicacion de un
	* usuario concreto
	*
	* @param app Aplicacion
	* @param user Nombre del usuario a buscar
	* @return Posicion del usuario en el vector de usuarios de la aplicacion o -1
	*         si el usuario no existe
	*/
	int get_user(collaboration::MIApplication* app, const char* user);
	
	/**
	* Obtiene la posicion en el vector de roles de una aplicacion de un
	* rol concreto
	*
	* @param app Aplicacion
	* @param role Nombre del rol a buscar
	* @return Posicion del rol en el vector de roles de la aplicacion o -1
	*         si el rol no existe
	*/
	int get_role(collaboration::MIApplication* app, const char* role);
	
	/**
	* Posicion de una aplicacion en el vector de aplicaciones
	*
	* @param app Nombre de la aplicacion a buscar
	* @return Posicion de la aplicacion en el vector de aplicaciones o -1
	*         si la aplicacion no existe
	*/
	int get_application_pos(const char* app);
	
public:
	
	/**
	* Constructor por defecto. Lee los datos del almacen de datos
	*/
	MIDataAccessor_impl();
	
	/**
	* Destructor
	*/
	virtual ~MIDataAccessor_impl();

	/**
	* Obtiene la lista de metainformacion de las aplicaciones
	*
	* @return Lista de metainformacion de las aplicaciones. Si no
	*         hay aplicaciones, devuelve una lista vacia (nunca NULL)
	*/
	collaboration::ListOfApplications* applications();
	
	/**
	* Agrega una aplicacion a la lista de aplicaciones del sistema
	*
	* @param app Nombre de la aplicacion a agregar
	* @return True si se pudo agregar la aplicacion. False si ya
	*         existia una aplicacion con igual nombre en el sistema.
	*/
	CORBA::Boolean add_application(const char* app);
	
	/**
	* Elimina una aplicacion de la lista de aplicaciones del sistema
	*
	* @param app Nombre de la aplicacion a eliminar
	* @return True si se pudo eliminar la aplicacion. False si no
	*         existia una aplicacion con ese nombre en el sistema.
	*/
	CORBA::Boolean remove_application(const char* app);
	
	/**
	* Loguea a un usuario en el sistema
	*
	* @param app Aplicacion
	* @param user Nombre del usuario a loguear
	* @param pass Password del usuario
	* @return Metainformacion de la conexion realizada. Si hubo algun error,
	*         el campo error_message de la estructura tendra un valor
	*         distinto a la cadena vacia.
	*/
	collaboration::MIConnection* login(const char* app, const char* user, const char* pass);
	
	/**
	* Pone un usuario como conectado. NO se llama automaticamente al llamar
	* al metodo login. Hay que llamarlo explicitamente.
	*
	* @param app Aplicacion del usuario en la que conectarse
	* @param user Usuario a conectar
	* @return Rol que desempeña el usuario o NULL si no pudo conectarse (no existe)
	*/
	char* connect_user(const char* app, const char* user);
	
	/**
	* Pone a un usuario como desconectado.
	*
	* @param app Aplicacion del usuario a desconectar
	* @param user Usuario a desconectar
	*/
	void disconnect_user(const char* app, const char* user);
	
	/**
	* Actualiza la marca de tiempo de un usuario. Si esta marca
	* no se actualiza, pasado un cierto tiempo, el usuario debera ser
	* desconectado.
	*
	* @param app Aplicacion del usuario al cual actualizar su marca de tiempo
	* @param user Usuario al cual actualizar su marca de tiempo
	*/
	void update_user_time(const char* app, const char* user);
	
	/**
	* Cambia el rol de un usuario conectado
	*
	* @param app Aplicacion en la que esta conectado el usuario
	* @param user Usuario al cual cambiar el rol
	* @param role Rol nuevo del usuario
	* @return Nueva metainformacion de la conexion. Si ocurrio algun error,
	*         entonces el campo error_message de la estructura sera distinto
	*         al valor cadena vacia (no NULL).
	*/
	collaboration::MIConnection* change_connected_user_role(const char* app, const char* user, const char* role);
	
	/**
	* Obtiene una lista de los usuarios conectados y sus roles actuales correspondientes
	*
	* @param app Aplicacion en la que se encuentran conectados los usuarios
	* @return Matriz con los usuarios y sus roles correspondientes. En la primera
	*         fila de la matriz estan los nombres de los usuarios y en la segunda los
	*         roles de cada uno de ellos. Devuelve NULL si ocurrio algun error.
	*/
	collaboration::ListOfUsersAndRoles* connected_users(const char* app);
	
	/**
	* Obtiene una lista con la metainformacion de los usuarios conectados
	*
	* @param app Aplicacion de la que obtener los usuarios conectados
	* @return Lista con la metainformacion de los usuarios conectados o NULL
	*         si ocurre algun error.
	*/
	collaboration::ListOfUsers* connected_users_info(const char* app);
	
	/**
	* Obtiene una lista con la metainformacion de los usuarios de una aplicacion
	*
	* @param app Aplicacion de la cual obtener la metainformacion de los usuarios
	* @return Lista con la metainformacion de los usuarios o NULL si ocurre algun
	*         error.
	*/
	collaboration::ListOfUsers* users_info(const char* app);
	
	/**
	* Obtiene una lista con la metainformacion de los roles de una aplicacion
	*
	* @param app Aplicacion de la cual obtener la metainformacion de los roles
	* @return Lista con la metainformacion de los roles o NULL si ocurre algun
	*         error.
	*/
	collaboration::ListOfRoles* roles_info(const char* app);
	
	/**
	* Obtiene la metainformacion de un rol
	*
	* @param app Aplicacion
	* @param role_name Nombre del rol
	* @return Metainformacion del rol o NULL si ocurre algun error
	*/
	collaboration::MIRole* role_info(const char* app, const char* role_name);
	
	/**
	* Obtiene la metainformacion de un usuario
	*
	* @param app Aplicacion
	* @param user_name Nombre del usuario
	* @return Metainformacion del usuario o NULL si ocurre algun error
	*/
	collaboration::MIUser* user_info(const char* app, const char* user_name);
	
	/**
	* Obtiene una lista con los nombres de los usuarios que pertenecen a un rol
	*
	* @param app Aplicacion a la que pertenecen los usuarios
	* @param role Nombre del rol
	* @return Lista con los nombres de los usuarios que pertenece al rol especificado
	*/
	collaboration::ListOfUserNames* role_users(const char* app, const char* role);
	
	/**
	* Obtiene una lista con los usuarios conectados cuya marca de tiempo no esta
	* actualizada
	*
	* @param app Aplicacion en la que se encuentran conectados los usuarios
	* @return Lista con los nombres de los usuarios o NULL si ocurrio algun error
	*/
	collaboration::ListOfUserNames* non_updated_users(const char* app);
	
	/**
	* Obtiene una lista con los nombres de los roles disponibles para una aplicacion
	*
	* @param app Aplicacion
	* @return Lista con los nombres de los roles disponibles para la aplicacion o NULL
	*        si ocurrio algun error.
	*/
	collaboration::ListOfRoleNames* application_roles(const char* app);
	
	/**
	* Obtiene una lista con los nombres de los usuarios disponibles para una aplicacion
	*
	* @param app Aplicacion
	* @return Lista con los nombres de los usuarios disponibles para la aplicacion o NULL
	*        si ocurrio algun error.
	*/
	collaboration::ListOfUserNames* application_users(const char* app);
	
	/**
	* Obtiene una lista con los nombres de los componentes disponibles para una aplicacion
	*
	* @param app Aplicacion
	* @return Lista con los nombres de los componentes disponibles para la aplicacion o NULL
	*        si ocurrio algun error.
	*/
	collaboration::ListOfComponentNames* application_components(const char* app);
	
	/**
	* Obtiene una lista con la metainformacion de los roles disponibles para un usuario
	*
	* @param app Aplicacion a la que pertenece el usuario
	* @param user Nombre del usuario
	* @return Lista con la metainformacion de los roles disponibles para un usuario o
	*         NULL si ocurrio algun error.
	*/
	collaboration::ListOfRoles* allowed_roles(const char* app, const char* user);
	
	/**
	* Obtiene una lista con los nombres de los roles disponibles para un usuario
	*
	* @param app Aplicacion a la que pertenece el usuario
	* @param user Nombre del usuario
	* @return Lista con los nombres de los roles disponibles para un usuario o
	*         NULL si ocurrio algun error.
	*/
	collaboration::ListOfRoleNames* allowed_role_names(const char* app, const char* user);
	
	/**
	* Obtiene el nivel de permisos de un componente para un usuario
	*
	* @param app Aplicacion
	* @param user Usuario
	* @param comp Componente
	* @return Nivel de permisos del componente o -1 si ocurrio algun error
	*/
	CORBA::Long get_user_component_permissions(const char* app, const char* user, const char* comp);
	
	/**
	* Asigna un nivel de permisos para un componente y un usuario concreto
	*
	* @param app Aplicacion
	* @param user Usuario
	* @param comp Componente
	* @param level Nivel de permisos nuevo para el componente y el usuario
	* @return True si se pudo asignar el nivel de permisos. False en caso contrario
	*/
	CORBA::Boolean set_user_component_permissions(const char* app, const char* user, const char* comp, CORBA::Long level);
	
	/**
	* Obtiene el nivel de permisos de un componente para un rol
	*
	* @param app Aplicacion
	* @param role Rol
	* @param comp Componente
	* @return Nivel de permisos del componente o -1 si ocurrio algun error
	*/
	CORBA::Long get_role_component_permissions(const char* app, const char* role, const char* comp);
	
	/**
	* Asigna un nivel de permisos para un componente y un rol concreto
	*
	* @param app Aplicacion
	* @param role Rol
	* @param comp Componente
	* @param level Nivel de permisos nuevo para el componente y el rol
	* @return True si se pudo asignar el nivel de permisos. False en caso contrario
	*/	
	CORBA::Boolean set_role_component_permissions(const char* app, const char* role, const char* comp, CORBA::Long level);
	
	/**
	* Obtiene el rol actual de un usuario
	*
	* @param app Aplicacion
	* @param user Usuario
	* @return Nombre del rol actual de un usuario o NULL si ocurrio algun error
	*/
	char* user_actual_role(const char* app, const char* user);
	
	/**
	* Crea un nuevo rol permitido para un usuario
	*
	* @param app Aplicacion
	* @param user Usuario
	* @param role Rol
	* @return True si se pudo crear el rol permitido o False en caso contrario.
	*/
	CORBA::Boolean new_user_allowed_role(const char* app, const char* user, const char* role);
	
	/**
	* Crea un nuevo usuario para una aplicacion
	*
	* @param app Aplicacion
	* @param user Usuario
	* @param password Clave
	* @param default_role Rol por defecto del usuario
	* @param is_admin Indica si es un usuario administrador o no
	* @return True si se pudo crear el usuario o False en caso contrario
	*/
	CORBA::Boolean new_user(const char* app, const char* user, const char* password, 
							const char* default_role, CORBA::Boolean is_admin);
							
	/**
	* Crea un nuevo rol para una aplicacion
	*
	* @param app Aplicacion
	* @param role Rol
	* @return True si se pudo crear el rol o False en caso contrario
	*/
	CORBA::Boolean new_role(const char* app, const char* role);
	
	/**
	* Elimina un rol permitido para un usuario
	*
	* @param app Aplicacion
	* @param user Usuario al que eliminar el rol permitido
	* @param role Rol a eliminar
	* @return True si todo fue correcto o False en caso contrario.
	*/
	CORBA::Boolean remove_allowed_user_role(const char* app, const char* user, const char* role);
	
	/**
	* Elimina un usuario de una aplicacion
	*
	* @param app Aplicacion
	* @param user Usuario
	* @return True si se pudo eliminar el usuario o False en caso contrario
	*/
	CORBA::Boolean remove_user(const char* app, const char* user);
	
	/**
	* Elimina un rol de una aplicacion
	*
	* @param app Aplicacion
	* @param role Rol
	* @return True si se pudo eliminar el rol o False en caso contrario
	*/
	CORBA::Boolean remove_role(const char* app, const char* role);
	
	/**
	* Obtiene una lista con los nombres de las aplicaciones del sistema
	*
	* @return Lista con los nombres de las aplicaciones del sistema
	*/
	collaboration::ListOfApplicationNames* get_applications_names();
	
	/**
	* Obtiene la metainformacion de una aplicacion
	*
	* @param name Nombre de la aplicacion
	* @return Metainformacion de la aplicacion o NULL si ocurrio algun error
	*/
	collaboration::MIApplication* get_application(const char* name);
	
	/**
	* Guarda la metainformacion del sistema de manera persistente
	*/
	void commit();
};

#endif
